package com.jfm.jfmc.plugin.snmp.collect;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.jfm.jfmc.plugin.icmp.collect.ICMPCollect;
import com.jfm.jfmc.plugin.icmp.enums.ResultValue;
import com.jfm.jfmc.plugin.snmp.entity.SNMPEntity;
import com.jfm.jfmc.plugin.snmp.entity.SNMPResponse;
import com.jfm.jfmm.collector.driver.ACollectorDriver;
import com.jfm.jfmm.collector.driver.SNMPDriver;
import com.jfm.jfmm.collector.entity.collect.CollectResult;
import com.jfm.jfmm.collector.entity.collect.Param;
import com.jfm.jfmm.collector.entity.collect.param.ICMPParam;
import com.jfm.jfmm.collector.entity.collect.param.SNMPParam;
import com.jfm.jfmm.collector.entity.collect.result.ICMPResult;
import com.jfm.jfmm.collector.entity.collect.result.SNMPResult;
import com.jfm.jfmm.collector.entity.collect.CheckResult;
import com.jfm.jfmm.collector.enums.ResultType;
import com.jfm.jfmm.collector.enums.snmp.SNMPMethod;
import com.jfm.jfmc.plugin.snmp.utils.SNMPUtil;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author DYang
 * @since 2024-10-09 22:31
 * SNMP 数据采集器
 */
@Slf4j
@Service
public class SNMPCollect extends SNMPDriver {

    @PostConstruct
    @Override
    public void register() {
        ACollectorDriver.collectorMap.put(this.supportProtocol(), this);
    }

    @Override
    public CheckResult perCheck(Param reqParam) {
        SNMPParam param  = this.transformParam(reqParam);

        if (param == null) return new CheckResult(ResultType.EMPTY_PARAM);

        if (param.getProtocol() == null) return new CheckResult(ResultType.EMPTY_PARAM,"snmp protocol is required");

        if (StrUtil.isBlank(param.getOids())) return new CheckResult(ResultType.EMPTY_PARAM,"snmp oid is required");

        if (StrUtil.isBlank(param.getHost())) return new CheckResult(ResultType.EMPTY_PARAM,"snmp ip is required");

        if (StrUtil.isBlank(param.getCommunity())) return new CheckResult(ResultType.EMPTY_PARAM,"snmp community is required");

        if (param.getPort() == null) return new CheckResult(ResultType.EMPTY_PARAM,"snmp port is required");

        if (param.getOids() == null) return new CheckResult(ResultType.EMPTY_PARAM,"snmp oid is required");

        return new CheckResult(ResultType.SUCCESS);
    }

    @Override
    public boolean isAvailable(Param reqParam) {
        SNMPParam param  = this.transformParam(reqParam);
        // 根据OID 监测采集是否正常
        if (param.isCheckOid()) {
            CollectResult collect = this.collect(param);
            return collect.getResult().getValue() != null;
        }

        // 是否检测SNMP 可用性，SNMP 为UDP协议，只能检测网络是否通
        if (param.isCheckHost()) {
            ICMPParam icmpParam = new ICMPParam();
            icmpParam.setHost(param.getHost());
            CollectResult collect = new ICMPCollect().collect(icmpParam);
            return ResultValue.SUCCESS.getValue() == ((ICMPResult) collect.getResult()).getResult();
        }
        return true;
    }

    @Override
    public CollectResult collect(Param reqParam) {
        long startTime = System.currentTimeMillis();
        SNMPParam param  = this.transformParam(reqParam);

        CollectResult collectResult = new CollectResult().protocol(this.supportProtocol()).startTime(startTime).responseTime(0);
        SNMPResult snmpResult = SNMPResult.build()
                .host(param.getHost()).port(param.getPort())
                .method(param.getMethod()).protocol(param.getProtocol())
                .community(param.getCommunity());

        CheckResult checkResult = this.perCheck(reqParam);
        if (checkResult.getResultType() != ResultType.SUCCESS) {
            snmpResult.errorMsg(checkResult.getMsg());
        }else {
            try {
                SNMPEntity snmpEntity = new SNMPEntity();
                BeanUtil.copyProperties(param,snmpEntity);
                SNMPMethod method = param.getMethod();

                SNMPResponse snmpResponse = null;
                Map<String, String> map = null;
                if ("get".equalsIgnoreCase(method.getMethod())) {
                    snmpResponse = SNMPUtil.getSnmp(param.getMetricId(), snmpEntity);
                    map = snmpResponse.getResult();
                }else {
                    snmpResponse = SNMPUtil.walkSnmp(param.getMetricId() , snmpEntity);
                    map = snmpResponse.getResult();
                }
                // 转换数据类型
                Map<String, Object> resMap = new HashMap<>();
                if (map != null) {
                    for (Map.Entry<String, String> entry : map.entrySet()) {
                        String value = entry.getValue();
                        Object valObj = this.transformValue(value, param.getDataType());
                        resMap.put(entry.getKey(), valObj);
                    }
                }
                snmpResult.setValue(resMap);

                long responseTime = System.currentTimeMillis() - startTime;

                // 构建返回数据
                snmpResult.errorMsg(snmpResponse.getErrorMsg());
                collectResult.responseTime(responseTime);
                collectResult.result(snmpResult);

            } catch (IOException e) {
                log.error("snmp collect error", e);
            }
        }
        return collectResult;
    }

}
